package com.fast.cron.db;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

/**
 * create data base and some tables
 *
 * @author :leo.jie
 * @version :v1.0
 * @date :2018/9/29 16:53
 */
public class DatabaseSetup {
    private static final String SQL_SCRIPT_PREFIX = "create.";
    private static final String SQL_SCRIPT_SUFFIX = ".sql";

    private String scriptPath;

    public DatabaseSetup(final String scriptPath) {
        this.scriptPath = scriptPath;
    }

    public void updateDatabase() throws SQLException, IOException {
        final Set<String> tables = collectAllTables();
        createTables(tables);
    }

    private Set<String> collectAllTables() {
        final Set<String> tables = new HashSet<>();
        final File directory = new File(this.scriptPath);
        final File[] createScripts = directory.listFiles(new PrefixSuffixFileFilter(SQL_SCRIPT_PREFIX, SQL_SCRIPT_SUFFIX));
        if (null != createScripts) {
            for (final File script : createScripts) {
                final String name = script.getName();
                final String[] nameSplit = name.split("\\.");
                final String tableName = nameSplit[1];
                tables.add(tableName);
            }
        }
        return tables;
    }

    private void createTables(final Set<String> tables) throws SQLException, IOException {
        final Connection conn = HikariDataSourceHelper.getConnection();
        conn.setAutoCommit(false);
        try {
            for (final String table : tables) {
                runTablesScripts(conn, table);
            }
        } finally {
            conn.close();
        }
    }

    private void runTablesScripts(final Connection conn, final String table) throws IOException, SQLException {
        final String dbScriptName = "create." + table + ".sql";
        System.out.println();
        final File script = new File(this.scriptPath, dbScriptName);
        BufferedInputStream buff = null;
        try {
            buff = new BufferedInputStream(new FileInputStream(script));
            final String queryStr = IOUtils.toString(buff);
            final String[] splitQuery = queryStr.split(";\\s*\n");
            final QueryRunner runner = new QueryRunner();
            for (final String query : splitQuery) {
                runner.update(conn, query);
            }
            conn.commit();

        } finally {
            IOUtils.closeQuietly(buff);
        }
    }

    public static class PrefixSuffixFileFilter implements FileFilter {

        private final String prefix;
        private final String suffix;

        PrefixSuffixFileFilter(final String prefix, final String suffix) {
            this.prefix = prefix;
            this.suffix = suffix;
        }

        @Override
        public boolean accept(final File pathname) {
            if (!pathname.isFile() || pathname.isHidden()) {
                return false;
            }

            final String name = pathname.getName();
            final int length = name.length();
            return this.suffix.length() <= length && this.prefix.length() <= length && name
                    .startsWith(this.prefix) && name.endsWith(this.suffix);
        }
    }
}
